package com.hlg.xboot.web.controller;

import com.hlg.xboot.config.AppConfig;
import com.hlg.xboot.core.DateEditor;
import com.hlg.xboot.exceptions.ErrorCode;
import com.hlg.xboot.exceptions.ServerBizException;
import com.hlg.xboot.vo.RestBody;
import com.hlg.xboot.constants.AppConstants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.ServletRequestDataBinder;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.InitBinder;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.Date;
import java.util.Set;

/**
 * <p>Description: 所有控制器的基类</p>
 * <p>Copyright: Copyright (c) 2016</p>
 * <p>Company: 中视数讯</p>
 * <p>Site: www.digi-zones.com</p>
 * <p>myblog: http://blog.csdn.net/xyang81</p>
 *
 * @author 杨信
 * @version 1.0
 * @date 2016/11/2
 */
public abstract class BaseController {

    protected final Logger logger = LoggerFactory.getLogger(getClass());

    @Autowired
    protected AppConfig appConfig;
    @Autowired
    protected RedisTemplate<String, Object> redisTemplate;

    protected  <T> T getLoginUser(HttpServletRequest request) {
        return (T) request.getSession().getAttribute(AppConstants.SESSION_USER);
    }

    protected void saveLoginUser(Object user, HttpServletRequest request) {
        request.getSession().setAttribute(AppConstants.SESSION_USER, user);
    }

    protected void removeLoginUser(HttpServletRequest request) {
        request.getSession().removeAttribute(AppConstants.SESSION_USER);
        request.getSession().invalidate();
    }

    /**
     * 异常统一处理
     *
     * @param request
     * @param response
     * @param handler
     * @param ex
     */
    @ExceptionHandler
    public RestBody resolveException(HttpServletRequest request, HttpServletResponse response,
                                     Object handler, Exception ex) {
        // 前端Rest接口异常处理
        if (handler instanceof ConstraintViolationException) {
            logger.error("数据约束异常: ", ex);
            Set<ConstraintViolation<?>> violations = ((ConstraintViolationException) handler).getConstraintViolations();
            String message = ErrorCode.PARAMETERS_ERROR.getRemark();
            for (ConstraintViolation violation : violations) {
                message = violation.getMessage();
                break;
            }
            return failure(ErrorCode.PARAMETERS_ERROR.getCode(), message);
        } else if (handler instanceof ServerBizException) { // 业务逻辑异常
            ServerBizException bizException = (ServerBizException) ex;
            ErrorCode errorCode = bizException.getErrCode();
            logger.error("业务逻辑异常: {}, {}", errorCode, ex);
            return failure(errorCode.getCode(), ex.getMessage());
        } else {    // 其它异常
            logger.error("系统异常", ex);
            return failure();
        }
    }

    /**
     * 请求成功
     * @param data      数据
     * @param errorCode 响应码
     * @return
     */
    protected RestBody success(Object data, ErrorCode errorCode) {
        RestBody result = new RestBody();
        result.setCode(errorCode.getCode());
        result.setData(data);
        return result;
    }

    protected RestBody success(Object data) {
        return success(data, ErrorCode.SERVER_OK);
    }

    protected RestBody success() {
        return success(null);
    }

    /**
     * 响应失败
     *
     * @param code    错误码
     * @param message 错误描述信息
     * @return
     */
    protected RestBody failure(Integer code, String message) {
        RestBody result = new RestBody();
        result.setCode(code);
        result.setMessage(message);
        return result;
    }

    protected RestBody failure() {
        return failure(ErrorCode.SERVER_SYSERR.getCode(), ErrorCode.SERVER_SYSERR.getRemark());
    }

    protected RestBody failure(String message) {
        return failure(ErrorCode.SERVER_SYSERR.getCode(), message);
    }

    /**
     * 日期类型绑定解析 yyyy-MM-dd HH:mm:ss
     * @param binder
     */
    @InitBinder
    public void InitBinder(ServletRequestDataBinder binder) {
        binder.registerCustomEditor(Date.class, new DateEditor());
    }

}
